package com.bitoon.basketdudes.ws;

import com.bitoon.basketdudes.jpa.Acumuladowbc;
import com.bitoon.basketdudes.jpa.Elo;
import com.bitoon.basketdudes.jpa.Equipo;
import com.bitoon.basketdudes.jpa.Usuario;
import com.bitoon.basketdudes.jpa.PersistenceManager;
import com.bitoon.basketdudes.jpa.RankingAcumulado;
import com.bitoon.basketdudes.jpa.RankingDivision;
import com.bitoon.basketdudes.jpa.RankingElo;
import com.bitoon.basketdudes.jpa.Region;
import com.bitoon.basketdudes.jpa.RegionZona;
import com.bitoon.basketdudes.ws.LoginAction;
import java.io.PrintWriter;
import java.util.List;

import javax.persistence.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.log4j.Logger;
/**
 * @author paco
 * 
 * Funciones 
 * 
 */
public class Central {
    Logger          log         = Logger.getLogger(Central.class);
    
    // Busca la zona de un Juego con el orden mayor de todos
    public int zonaMayor ( EntityManager p_em, int p_region_id, int p_juego_id ) {
        
        List<RegionZona> l_acumulado=zonasRegionJuego ( p_em,p_region_id,p_juego_id );

        if ( l_acumulado!= null && l_acumulado.size()>0 ) {
            log.debug( " REGION ENCONTRADA " + l_acumulado.get(0).getId()  );
            return l_acumulado.get(0).getZonaId();
        } else {
            return 0;
        }
    }
    
    // Busca todas la zonas permitidas para una región y un Juego
    public List<RegionZona> zonasRegionJuego ( EntityManager p_em, int p_region_id, int p_juego_id ) {    
        try {
            // Buscamos el ranking acumulado de un equipo
            Query q_zona = p_em.createNamedQuery("RegionZona.findByRegion");
            q_zona.setParameter("juego_id" , p_juego_id );
            q_zona.setParameter("region_id", p_region_id );

            List<RegionZona> l_acumulado = q_zona.getResultList();
            
            if ( l_acumulado.size()>0 )
                return l_acumulado;
            else
                return null;

        } catch (NoResultException nre) {
            log.info("[TRAZA][zonasRegionJuego no encontrada]: " + p_region_id + " juego " + p_juego_id );
            return null;
        } 
    }

    public void wsCambioRegionUsuario ( HttpServletRequest request, HttpServletResponse response ) {
        int         usuario_id  = 0;
        int         region_id   = 0;
        int         error       = 0;
        String      sesion      ="";
        PrintWriter out         = null;     
        
        try {
            out = response.getWriter();     
        
            if ( request.getParameter("usuario_id")!= null ) {
                usuario_id = Integer.parseInt(request.getParameter("usuario_id"));
            } 
            if ( request.getParameter("region_id") != null ) {
                region_id  = Integer.parseInt(request.getParameter("region_id"));
            }
            if ( request.getSession().getId() != null ) {
                sesion = request.getSession().getId();
            }
            error = cambioRegionUsuario ( sesion, usuario_id, region_id );
        } catch (Exception e) {
            error = -100;
        }
        if ( out != null)
            out.print ( "error="+error+";" );    
    }
    
    
    // Realiza el cambio de Region y Zona para un usuario
    // Actualiza el usuario con el nuevo identificador de region
    // Actualiza todos los equipos del usuario con la zona mayor de la región.
    // Borra los rankings actuales de los equipos 
    
    // Retorno:
    //  0 - ok
    // -1 - Error indeterminado
    // -2 - User not exists
    // -3 - Same Region
    // -4 - Region not exists 
    // -5 - Incorrect parameters
    // -6 - Invalid Session
    
    public int cambioRegionUsuario ( String p_sesion, int p_usuario_id, int p_region_id ) {    
        EntityManager em=null;
        int error=0;
               
        try {    
            if ( p_usuario_id<1 || p_region_id<1 ) {
                throw new ExcepcionGeneral( -5, "Incorrect Parameters" );                
            }
            
            EntityManagerFactory emf = PersistenceManager.getInstance().getEntityManagerFactory("jpa_basket");
            em = emf.createEntityManager(); 
            em.getTransaction().begin();
            
            LoginAction la = new LoginAction();
            int usuario_id = la.comprobarSesion( p_sesion, em);
            if ( usuario_id != p_usuario_id ) {
                log.error("Sesión Incorrecta "+p_sesion+" "+p_usuario_id+":"+p_usuario_id);
                throw new ExcepcionGeneral( -6, "Invalid Session" );                
            }
            
            Query q_usuario = em.createNamedQuery("Usuario.findById");
            q_usuario.setParameter("id", p_usuario_id);
            List<Usuario> l_usuario = q_usuario.getResultList();
            if ( l_usuario.size()==0 ) {
                throw new ExcepcionGeneral( -2, "User not exists" );                
            } 
            Usuario u = l_usuario.get(0);

            if ( u.getRegion().getId() == p_region_id ) {
                throw new ExcepcionGeneral( -3, "Same Region" );                
            }
            
            Query q_region = em.createNamedQuery("Region.findById");
            q_region.setParameter("id", (short)p_region_id);
            List<Region> l_region = q_region.getResultList();
            if ( l_region.size()==0 ) {
                throw new ExcepcionGeneral( -4, "Region not exists" );                
            } 
            Region region = l_region.get(0);
            
            u.setRegion(region);
            
            // Tomamos como nueva zona la mayor de la region
            int zona_id= zonaMayor( em, p_region_id, 1 );
            
            // Buscamos todos los equipos del usuario para cambiarle la zona
            Query q_equipo = em.createNamedQuery("Equipo.findByIdUsuario");
            q_equipo.setParameter("idUsuario", p_usuario_id);
            List<Equipo> l_equipo = q_equipo.getResultList();
           
            for ( int i=0;i<l_equipo.size();i++){
                Equipo equipo = l_equipo.get(i);
            
                cambioZonaEquipo ( em, equipo, zona_id );
            }
            
            em.getTransaction().commit();
            
        } catch (ExcepcionGeneral ex) {            
            log.error("error="+ex.getCodigo()+";descripcion="+ex.getDescripion(),ex);
            error = ex.getCodigo();
        } catch (Exception e) {
            error = -1;
            log.error("[cambioRegionUsuario]: " , e);
            try { em.getTransaction().rollback(); } catch (Exception e2) { }
            
        } finally {
            try { em.close(); } catch (Exception e) { } 
        }
        return error;        
    }

    
    // Realiza el cambio de Zona para un equipo
    // Actualiza el equipo con la zona pasada como parámetro.
    // Actualiza el elo con la zona pasada como parámetro y pone a 0 su división y sus puntos de division
    // Borra los rankings actuales de los equipos.
    
    // Retorno:
    //  0 - ok
    // -1 - Error indeterminado
    // -2 - User not exists
    // -3 - Same Region
    // -4 - Region not exists 
    
    private int cambioZonaEquipo ( EntityManager em, Equipo p_equipo, int p_zona_id ) {    
        int error=0;
        
        p_equipo.setZonaId(p_zona_id);

        Query q_elo = em.createNamedQuery("Elo.findByEquipoId");
        q_elo.setParameter("equipo_id", p_equipo.getId() );
        List<Elo> l_elo = q_elo.getResultList();

        for ( int y=0;y<l_elo.size();y++){
            Elo elo = l_elo.get(0);
            elo.setZona(p_zona_id);
            elo.setDivision(0);
            elo.setGanados(0);
            elo.setPerdidos(0);
            elo.setDivisionPuntos(0);
        }
        if (true){ // Borrado de RankingDivision
            Query q_ranking = em.createNamedQuery("RankingDivision.findByEquipoId");
            q_ranking.setParameter("equipoId", p_equipo.getId() );
            List<RankingDivision> l_ranking = q_ranking.getResultList();

            for ( int z=0;z<l_ranking.size();z++){
                RankingDivision ranking= l_ranking.get(0);
                em.remove(ranking);
            }
        }                    
        if (true){ // Borrado de RankingAcumulado
            Query q_ranking = em.createNamedQuery("RankingAcumulado.findByEquipoId");
            q_ranking.setParameter("equipoId", p_equipo.getId() );
            List<RankingAcumulado> l_ranking = q_ranking.getResultList();

            for ( int z=0;z<l_ranking.size();z++){
                RankingAcumulado ranking= l_ranking.get(0);
                em.remove(ranking);
            }
        }                    
        if (true){ // Borrado de RankingElo
            Query q_ranking = em.createNamedQuery("RankingElo.findByEquipoId");
            q_ranking.setParameter("equipoId", p_equipo.getId() );
            List<RankingElo> l_ranking = q_ranking.getResultList();

            for ( int z=0;z<l_ranking.size();z++){
                RankingElo ranking= l_ranking.get(0);
                em.remove(ranking);
            }
        }                    
        if (true){ // Borrado de AcumuladoWBC
            Query q_ranking = em.createNamedQuery("Acumuladowbc.findByEquipoId");
            q_ranking.setParameter("equipo_id", p_equipo.getId() );
            List<Acumuladowbc> l_ranking = q_ranking.getResultList();

            for ( int z=0;z<l_ranking.size();z++){
                Acumuladowbc ranking= l_ranking.get(0);
                em.remove(ranking);
            }
        }                                    
        return error;        
    }    
    
}
